<?php
namespace App\SDK\PingAn\service;

use App\SDK\PingAn\library\Rsa;
use App\SDK\PingAn\library\JWT;
use App\SDK\PingAn\library\Request;
use App\SDK\PingAn\library\Config;

class Download
{
    private $_rsa;

    public function request($fileNo, $saveFile)
    {
        $result = ['code' => 0, 'msg' => 'ok'];
        $config = Config::get();
        $data = [
            'appId' => $config['app_id'],
            'fileNo' => $fileNo,
            'container' => '01',
        ];
        $header = $this->getHeader($data);
        $url = $config['url']['download'];
        $file = Request::curlDownFile($url, $header);
        if ($GLOBALS['G_HTTP_CODE'] == 200) {
            file_put_contents($saveFile, $file);
            unset($file);
        } else {
            $result = ['code' => 2, 'msg' => '下载失败'];
        }
        return $result;
    }

    private function getHeader($data) {
        $data = [
            'User-Agent' => 'aop-sdk-php',
            'x-pab-signMethod' =>  !empty(Config::get('signature_method')) ? Config::get('signature_method') : 'RSA',
            'x-pab-version' => 'PHP-BOAP_1.0.0',
            'appId' => Config::get('app_id'),
            'fileNo' => $data['fileNo'],
            'sign' => $this->getSignature($data),
        ];
        return array_map(function ($key, $value){return $key . ': ' . $value;}, array_keys($data), $data);
    }
    private function getSignature($data)
    {
        $signature = '';
        if (Config::get('signature_method') == 'SM2') {
            $signature = $this->jwt()->sign(json_encode($data));
        } else {
            $signature = $this->getSign($data);
        }
        return $signature;
    }
    private function getSign($str) {
            if (is_array($str)) {
                $arr = []; $result = [];
                $this->assemble('', $str, $arr);
                ksort($arr); unset($arr['filePathName']);
                foreach ($arr as $key => $value) {
                    $result[] = $key . '=' . $value;
                }
                $str = implode('&', $result) . '&';
            }
            return $this->rsa()->sign($str);
    }

    private function assemble($prev, $data, &$result) {
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $this->assemble($prev . (is_string($key) ? $key : ''), $value, $result);
            } else {
                if ($value !== '') {
                    $result[$prev . $key] = $value;
                }
            }
        }
        return $result;
    }

    private function rsa() {
        if (is_null($this->_rsa)) {
            $this->_rsa = new Rsa();
        }
        return $this->_rsa;
    }
}
